package cn.zebra.dev.admin.module.role.service.impl;

import cn.zebra.dev.admin.module.role.dao.AdminRoleMenuDao;
import cn.zebra.dev.admin.module.role.entity.AdminRoleMenuEntity;
import cn.zebra.dev.admin.module.role.service.AdminRoleMenuService;
import cn.zebra.dev.ibatis.plus.service.impl.ServiceImpl;
import cn.zebra.dev.ibatis.plus.utils.PageUtils;
import cn.zebra.dev.ibatis.plus.utils.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.SneakyThrows;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.Future;

import static java.util.stream.Collectors.toList;

/**
 * 后台角色与菜单对应关系
 *
 * @author runnable
 * @date 2019-09-07 17:02:18
 */
@Service
public class AdminRoleMenuServiceImpl extends ServiceImpl<AdminRoleMenuDao, AdminRoleMenuEntity> implements AdminRoleMenuService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AdminRoleMenuEntity> page = this.page(
                new Query<AdminRoleMenuEntity>(params).getPage(),
                new QueryWrapper<>()
        );

        return new PageUtils<>(page);
    }

    @Override
    public List<Long> queryMenuIdList(Long roleId) {
        List<AdminRoleMenuEntity> list = selectList("menu_id", "role_id = {0}", roleId);
        return list.stream().map(AdminRoleMenuEntity::getMenuId).collect(toList());
    }

    @Override
    public boolean saveOrUpdate(Long roleId, List<Long> menuIdList) {
        //先删除角色与菜单关系
        deleteRoleBatch(Collections.singleton(roleId));
        if (menuIdList.size() == 0) {
            return true;
        }

        //保存角色与菜单关系
        List<AdminRoleMenuEntity> list = new ArrayList<>(menuIdList.size());
        menuIdList.stream().filter(menuId -> menuId > 0).forEach(menuId -> {
            AdminRoleMenuEntity sysRoleMenuEntity = new AdminRoleMenuEntity();
            sysRoleMenuEntity.setMenuId(menuId);
            sysRoleMenuEntity.setRoleId(roleId);
            list.add(sysRoleMenuEntity);
        });
        return this.saveBatch(list);
    }

    private Boolean deleteRoleBatch(Collection<Long> roleIds) {
        return remove(new QueryWrapper<AdminRoleMenuEntity>().in("role_id", roleIds));
    }

    @SneakyThrows
    @Override
    public boolean saveBatch(Collection<AdminRoleMenuEntity> entityList) {
        if (entityList != null && entityList.size() > 0) {
            List<Future<Boolean>> list = new ArrayList<>(entityList.size());
            entityList.forEach(entity -> list.add(this.asyncSave(entity)));
            for (int i = list.size() - 1; i >= 0; i--) {
                if (!list.get(i).get()) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    @Async
    public Future<Boolean> asyncSave(AdminRoleMenuEntity entity) {
        return AsyncResult.forValue(this.save(entity));
    }
}
